﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using AppFabric.ServiceBus.Common;
using AppFabric.ServiceBus.CommonForms;
using Microsoft.ServiceBus.Messaging;

namespace AppFabric.ServiceBus.ReceiveClient
{
    public partial class ReceiveForm : Form
    {
        ServiceBusHelper helper = null;
        bool isConnected = false;
        List<AppFabric.ServiceBus.Common.Message> messageList = new List<Common.Message>();
        Timer timer = new Timer();
        bool pollingInProgress = false;

        public ReceiveForm()
        {
            InitializeComponent();
            dgvMessages.AutoGenerateColumns = false;
            timer.Tick += new EventHandler(TimerElapsed);
            timer.Enabled = false;
        }

        #region Private Methods
        private void connectToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (!isConnected)
            {
                ConnectForm connectForm = new ConnectForm();
                connectForm.ShowDialog();
                if (connectForm.DialogResult == System.Windows.Forms.DialogResult.OK)
                {
                    try
                    {
                        ServiceBusNamespace token = new ServiceBusNamespace(connectForm.Namespace,
                                    connectForm.ServicePath,
                                    connectForm.IssuerName,
                                    connectForm.IssuerKey);
                        helper = new ServiceBusHelper();
                        helper.Token = token;
                        isConnected = helper.Connect();
                        connectToolStripMenuItem.Text = "Disconnect";
                    }
                    catch
                    {
                        MessageBox.Show("Test client was unable to Connect. Please enter correct credentials.");
                    }
                }
            }
            else
            {
                helper = null;
                isConnected = false;
                connectToolStripMenuItem.Text = "Connect";
            }
        }

        private void cboCommunicationObject_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!CheckConnection())
                return;

            gbCommunicationObject.Text = "Choose " + cboCommunicationObject.SelectedItem.ToString();
            try
            {
                lblStatus.Text = "Loading " + cboCommunicationObject.SelectedItem.ToString() + "s from Namespace...";
                switch (cboCommunicationObject.SelectedItem.ToString())
                {
                    case "Queue":
                        {
                            cboDescriptions.DataSource = helper.GetQueues().Select(p => p.Path).ToList();
                            cboSubscription.Enabled = false;
                            break;
                        }
                    case "Topic":
                        {
                            cboDescriptions.DataSource = helper.GetTopics().Select(p => p.Path).ToList();
                            cboSubscription.Enabled = true;
                            break;
                        }
                }
                lblStatus.Text = "Completed";
            }
            catch 
            {
                MessageBox.Show("Test client was unable to fetch " + cboCommunicationObject.SelectedItem.ToString() + "s");
                lblStatus.Text = "Error occured";
            }
        }

        private void cboDescriptions_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!CheckConnection())
                return;
            try
            {
                if (cboCommunicationObject.SelectedItem.ToString() == "Topic")
                {
                    lblStatus.Text = "Loading Subscriptions...";
                    cboSubscription.DataSource = helper.GetSubscriptions(cboDescriptions.SelectedValue.ToString()).Select(p => p.Name).ToList();
                    lblStatus.Text = "Completed";
                }
            }
            catch
            {
                MessageBox.Show("Test client was unable to fetch Subscriptions.");
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            if (!pollingInProgress)
            {
                if (!CheckConnection())
                    return;
                if (!ValidateControls())
                    return;

                pollingInProgress = true;
                timer.Interval = int.Parse(txtPollInterval.Text) * 1000;
                timer.Enabled = true;
                timer.Start();
                btnOk.Text = "Stop Polling";
                lblStatus.Text = "Polling Started...";
            }
            else
            {
                timer.Stop();
                timer.Enabled = false;
                pollingInProgress = false;
                btnOk.Text = "Poll";
                lblStatus.Text = "Polling Stopped";
            }
            
        }

        private void TimerElapsed(object sender, EventArgs e)
        {
            timer.Stop();
            try
            {
                List<AppFabric.ServiceBus.Common.Message> receviedMessages = null;
                lblStatus.Text = "Receiving Messages...";
                switch (cboCommunicationObject.SelectedItem.ToString())
                {
                    case "Queue":
                        {
                            receviedMessages = helper.ReceiveQueueMessages(cboDescriptions.SelectedValue.ToString(), GetMode());
                            break;
                        }
                    case "Topic":
                        {
                            receviedMessages = helper.ReceiveSubscriptionMessages(cboDescriptions.SelectedValue.ToString(),
                                cboSubscription.SelectedValue.ToString(), GetMode());
                            break;
                        }
                }
                messageList = messageList.Concat(receviedMessages).ToList();
                dgvMessages.DataSource = messageList;
                lblStatus.Text = "Messages Received";
                lblMessageCount.Text = "Message Count: " + messageList.Count.ToString();
                lblStatus.Text = "Waiting to Poll..";
                timer.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Test client was unable to receive a message. Please contact Administrator.");
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private bool CheckConnection()
        {
            if (!isConnected)
            {
                MessageBox.Show("Please Connect to Windows AppFabric ServiceBus first.");
            }
            return isConnected;
        }

        private ReceiveMode GetMode()
        {
            ReceiveMode mode = new ReceiveMode();
            if (rdbReadandDelete.Checked)
                mode = ReceiveMode.ReceiveAndDelete;
            else
                mode = ReceiveMode.PeekLock;
            return mode;
        }

        private void dgvMessages_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            var message = messageList[e.RowIndex];
            txtContentType.Text = message.ContentType == null ? string.Empty : message.ContentType;
            txtCorrelationId.Text = message.CorrelationId == null ? string.Empty : message.CorrelationId;
            txtLabel.Text = message.Label == null ? string.Empty: message.Label ;
            txtMessageId.Text = message.MessageId;
            txtSessionId.Text = message.SessionId == null ? string.Empty : message.SessionId;
            txtTTL.Text = message.TimeToLive.TotalSeconds.ToString();
            rtbPayLoad.Text = message.MessageBody;
            dgvProperties.DataSource = message.MessageProperties.Select(p=> new {p.Key, p.Value}).ToList();
        }

        private bool ValidateControls()
        {
            bool result = true;
            if (cboCommunicationObject.SelectedItem == null)
            {
                MessageBox.Show("Please choose Communication Object.");
                result = false;
            }
            else
            {
                if (cboCommunicationObject.SelectedItem.ToString() == "Topic")
                {
                    if (cboDescriptions.Items.Count == 0)
                    {
                        MessageBox.Show("No Topics present in Namespace.");
                        result = false;
                    }
                    else if (cboSubscription.Items.Count == 0)
                    {
                        MessageBox.Show("No Subscrptions present for Topic.");
                        result = false;
                    }
                }
                else
                {
                    if (cboDescriptions.Items.Count == 0)
                    {
                        MessageBox.Show("No Queues present in Namespace.");
                        result = false;
                    }
                }
            }
            if (string.IsNullOrEmpty(txtPollInterval.Text))
            {
                MessageBox.Show("Please enter positive numeric Polling Interval");
                result = false;
            }
            else
            {
                int value;
                bool res = int.TryParse(txtPollInterval.Text, out value);
                if (!res || value == 0)
                {
                    MessageBox.Show("Please enter positive numeric Polling Interval");
                    result = false;
                }
            }
            return result;
        }
        #endregion

    }
}
